﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using Kokomo.Mirror.CliMetadata.Tables;

namespace Kokomo.Mirror.CliMetadata
{
	abstract class CliImplementedType : CliTypeBase
	{
		protected CliImplementedType(
			CliMemberBasicInfo basicInfo
			)
			: base(basicInfo)
		{
			this._interfaces = new Lazy<Type[]>(this.LoadInterfaces);

			//this._customAttributeData = new Lazy<IList<CustomAttributeData>>(this.LoadCustomAttributeData);
		}

		internal abstract TypeDefRow TypeDefRow { get; }

		#region Interfaces
		public override Type GetInterface(string name, bool ignoreCase)
		{
			Type[] interfaceTypes = this.GetInterfaces();
			StringComparison comparison = ignoreCase ? StringComparison.InvariantCultureIgnoreCase : StringComparison.InvariantCulture;
			Type interfaceType = interfaceTypes.Where(t => string.Equals(name, t.Name, comparison)).SingleOrDefault();

			return interfaceType;
		}

		private Lazy<Type[]> _interfaces;
		private Type[] LoadInterfaces()
		{
			return this.CliModule.QueryInterfacesForTypeDef(this);
		}
		public override Type[] GetInterfaces()
		{
			return this._interfaces.Value;
		}

		public override InterfaceMapping GetInterfaceMap(Type interfaceType)
		{
			return this.CliModule.QueryInterfaceMap(this, interfaceType);
		}
		#endregion
		#region Members

		#region Methods
		protected override MethodBase[] LoadDeclaredMethods()
		{
			Type[] genericArguments = this.GetGenericArguments();
			return this.CliModule.QueryMethodsForTypeDef(this, this);
		}
		#endregion
		#region Events
		protected override EventInfo[] LoadDeclaredEvents()
		{
			return this.CliModule.QueryEventsForTypeDef(this, this);
		}
		#endregion
		#region Fields
		protected override FieldInfo[] LoadDeclaredFields()
		{
			return this.CliModule.QueryFieldsForTypeDef(this, this);
		}
		#endregion
		#region Properties
		protected override PropertyInfo[] LoadDeclaredProperties()
		{
			return this.CliModule.QueryPropertiesForTypeDef(this, this);
		}
		#endregion
		#region Nested types
		protected override Type[] LoadDeclaredNestedTypes()
		{
			return this.CliModule.QueryNestedTypesForTypeDef(this, this);
		}
		#endregion
		#endregion
		#region Attributes

		//private Lazy<IList<CustomAttributeData>> _customAttributeData;
		private IList<CustomAttributeData> LoadCustomAttributeData()
		{
			return this.basicInfo.module.GetCustomAttributesFor(this.MetadataToken);
		}
		public override IList<CustomAttributeData> GetCustomAttributesData()
		{
			//return this._customAttributeData.Value;
			return this.LoadCustomAttributeData();
		}
		#endregion
	}
}
